package com.junrry.communication

import android.Manifest
import android.annotation.SuppressLint
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothManager
import android.bluetooth.BluetoothSocket
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Build
import android.os.Bundle
import android.text.TextUtils
import android.util.Log
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import com.junrry.communication.ktx.CustomGlobalScope
import com.junrry.communication.ktx.io
import com.junrry.communication.databinding.ActivityPcBinding
import java.io.IOException
import java.io.InputStream
import java.io.OutputStream
import java.util.UUID


private var PERMISSIONS_REQUIRED = arrayListOf<String>().apply {
    add(Manifest.permission.BLUETOOTH_SCAN)
    add(Manifest.permission.BLUETOOTH_CONNECT)
    add(Manifest.permission.ACCESS_COARSE_LOCATION)
    add(Manifest.permission.ACCESS_FINE_LOCATION)
}

private const val TAG = "BluetoothActivity_LJM"

class BluetoothActivity : ComponentActivity() {

    private lateinit var binding: ActivityPcBinding

    private lateinit var activityResultLauncher: ActivityResultLauncher<Array<String>>
    private lateinit var launcher: ActivityResultLauncher<Intent>

    private var bluDevice: BluetoothDevice? = null
    private lateinit var bluetoothAdapter: BluetoothAdapter

    private var str = StringBuilder()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityPcBinding.inflate(layoutInflater)
        setContentView(binding.root)
        registerBroadcastReceiver()
        requestPermissions()

        initListener()
    }

    private fun initListener() {
        binding.btnSend.setOnClickListener {
            if (outputStream != null) {
                if (binding.etSend.text.toString().trim().isNullOrEmpty()) {
                    Toast.makeText(this, "输入内容", Toast.LENGTH_LONG).show()
                    return@setOnClickListener
                }
                send(binding.etSend.text.toString().trim())
            } else {
                startBluetooth()
            }
        }
    }

    override fun onDestroy() {
        disconnectAndClose()
        super.onDestroy()
        unRegisterBroadcastReceiver()
    }

    private fun requestPermissions() {
        val contract = ActivityResultContracts.RequestMultiplePermissions()
        activityResultLauncher = registerForActivityResult(contract) { result ->
            var permissionGranted = true
            result.entries.forEach {
                if (it.key in PERMISSIONS_REQUIRED && !it.value)
                    permissionGranted = false
            }
            if (!permissionGranted) {
                Toast.makeText(this, "无权限", Toast.LENGTH_LONG).show()
            } else {
                initBluetooth()
            }
        }
        activityResultLauncher.launch(PERMISSIONS_REQUIRED.toTypedArray())

        launcher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
            if (it.resultCode == RESULT_OK) {
                Toast.makeText(this, "蓝牙已打开", Toast.LENGTH_LONG).show()
                startBluetooth()
            }
        }
    }

    fun initBluetooth() {
        val bluetoothManager = getSystemService(BLUETOOTH_SERVICE) as BluetoothManager
        bluetoothAdapter = bluetoothManager.adapter
        if (bluetoothAdapter == null) {
            Toast.makeText(this, "不支持蓝牙", Toast.LENGTH_LONG).show()
        } else {
            if (!bluetoothAdapter.isEnabled) {
                val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
                launcher.launch(enableBtIntent)
            } else {
                startBluetooth()
            }
        }
    }

    @SuppressLint("MissingPermission")
    fun startBluetooth() {
        if (bluetoothAdapter != null && !bluetoothAdapter.isDiscovering) {
            bluetoothAdapter.startDiscovery()
        }
    }

    fun registerBroadcastReceiver() {
        val filter = IntentFilter()
        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED)
        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)
        filter.addAction(BluetoothDevice.ACTION_FOUND)
        filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED)
        registerReceiver(broadcastReceiver, filter)
    }

    fun unRegisterBroadcastReceiver() {
        unregisterReceiver(broadcastReceiver)
    }

    @SuppressLint("MissingPermission")
    private fun startConnect() {
        connect(bluDevice?.address)
    }


    //蓝牙输入流输出流
    private var socket: BluetoothSocket? = null
    private var inputStream: InputStream? = null
    private var outputStream: OutputStream? = null
    //连接蓝牙
    @SuppressLint("MissingPermission")
    fun connect(address: String?): Boolean {
        bluetoothAdapter.cancelDiscovery()
        if (TextUtils.isEmpty(address)) {
            Log.w(TAG, "unspecified address.")
            return false
        }
        val device: BluetoothDevice = bluetoothAdapter.getRemoteDevice(address)
        if (device == null) {
            Log.w(TAG, "Device not found. Unable to connect.")
            return false
        }

        socket =
            device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
        socket?.connect()

        inputStream = socket?.inputStream
        outputStream = socket?.outputStream

        receiverData()

        return true
    }

    private fun receiverData() {
        CustomGlobalScope.io {
            val buffer = ByteArray(1024)
            var bytes: Int
            while (true) {
                try {
                    bytes = inputStream?.read(buffer)!!
                    val receivedMessage = String(buffer, 0, bytes)
                    // 处理接收到的消息
                    Log.d(TAG, "receivedMessage = $receivedMessage")
                } catch (e: IOException) {
                    // 处理异常
                    break
                }
            }
        }
    }

    /**
     * 发送数据
     */
    private fun send(msg: String) {
        if (outputStream == null) {
            Log.d(
                TAG,
                "outputStream == null: " + (outputStream == null)
            )
            return
        }
        Log.d(
            TAG,
            "msg : " + (msg)
        )
        val bytes = msg.toByteArray()
        try {
            outputStream?.write(bytes)
        } catch (e: IOException) {
            e.printStackTrace()
        }
    }


    @SuppressLint("MissingPermission")
    private fun disconnectAndClose() {

        if (bluetoothAdapter != null) {
            bluetoothAdapter.cancelDiscovery()
        }

        try {
            inputStream?.close()
            outputStream?.close()
            socket?.close()
        } catch (e: IOException) {
            e.printStackTrace()
        }
    }


    val broadcastReceiver = object : BroadcastReceiver() {
        @SuppressLint("MissingPermission")
        override fun onReceive(context: Context?, intent: Intent?) {
            Log.d(TAG, "onReceive ${intent?.action}")
            when (intent?.action) {
                BluetoothAdapter.ACTION_DISCOVERY_STARTED -> {
                    Toast.makeText(context, "开始搜索", Toast.LENGTH_LONG).show()
                }

                BluetoothAdapter.ACTION_DISCOVERY_FINISHED -> {
                    Toast.makeText(context, "搜索结束", Toast.LENGTH_LONG).show()
                }

                BluetoothDevice.ACTION_BOND_STATE_CHANGED -> {

                    val state =
                        intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.ERROR)

                    if (state == BluetoothDevice.BOND_BONDED) {
                        // 蓝牙设备已配对
                        Log.d("BluetoothBondReceiver", "设备已配对：" + bluDevice?.name)
                        startConnect()
                    } else if (state == BluetoothDevice.BOND_BONDING) {
                        // 蓝牙设备正在配对
                        Log.d("BluetoothBondReceiver", "设备正在配对：" + bluDevice?.name)
                    } else if (state == BluetoothDevice.BOND_NONE) {
                        // 蓝牙设备未配对
                        Log.d("BluetoothBondReceiver", "设备未配对：" + bluDevice?.name)
                    }

                }

                BluetoothDevice.ACTION_FOUND -> {

                    val device: BluetoothDevice? =
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                            intent.getParcelableExtra(
                                BluetoothDevice.EXTRA_DEVICE,
                                BluetoothDevice::class.java
                            )
                        } else {
                            intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)
                        }
                    Log.d(TAG, "ACTION_FOUND ${device?.name}")

                    //00:0E:0E:19:03:F0  98:D3:41:FE:32:5F 搜索到指定设备后停止搜索并连接
                    if (device?.address?.contains("98:D3:41:FE:32:5F") == true
                        && str.contains("98:D3:41:FE:32:5F") == false
                    ) {
                        bluDevice = device
                        var uuids = device?.getUuids();
                        if (uuids != null) {
                            for (uuid in uuids) {
                                Log.d(TAG, "UUID: " + uuid.toString());
                            }
                        } else {
                            Log.d(TAG, "该设备没有公开的 UUID")
                        }
                        if (device?.bondState == BluetoothDevice.BOND_NONE) {
                            // 未配对
                            Log.d(TAG, "未配对")
                            val method = BluetoothDevice::class.java.getMethod("createBond")
                            method.invoke(bluDevice)
                        } else {
                            // 已配对
                            Log.d(TAG, "已配对")
                            startConnect()
                        }
                    }

                    if (device?.address?.let { str.contains(it) } == false) {
                        str.append(device?.name + "     " + device?.address + "\n")
                        binding.tvDevice.text = str
                    }
                }
            }
        }
    }

}